
package com.yadong.smarthome2.control;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;

import com.yadong.smarthome2.connections.ResultListener;
import com.yadong.smarthome2.datastore.SmartHomeDbOperator;
import com.yadong.smarthome2.device.Device;
import com.yadong.smarthome2.device.DeviceManagerService;
import com.yadong.smarthome2.protocol2.ALog;
import com.yadong.smarthome2.protocol2.ResultProtocol.Result;

public class ControlCenterService extends Service implements ResultListener {
    private DeviceManagerService mDeviceManagerService;
    private Map<Device, List<ControlRules>> mDeviceControlRules =
            new HashMap<Device, List<ControlRules>>();
    private SmartHomeDbOperator mDbOperator;

    @Override
    public void onCreate() {
        super.onCreate();
        mDbOperator = new SmartHomeDbOperator(this);
        Intent intent = new Intent(this, DeviceManagerService.class);
        bindService(intent, mConnection, BIND_AUTO_CREATE);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mDeviceManagerService.removeResultListener(this);
    }

    private void loadRules() {
        List<ControlRules> controlRules = mDbOperator
                .getAllRules(mDeviceManagerService);
        for (ControlRules rule : controlRules) {
            addRule(rule.getDevice(), rule, false);
        }
    }

    private boolean saveRule(ControlRules rule) {
        if (checkRule(rule)) {
            return mDbOperator.saveRule(rule);
        } else {
            ALog.loge(this, "error to save rule. the rule is error");
            return false;
        }
    }

    private boolean checkRule(ControlRules rule) {
        // TODO check rules
        return true;
    }

    public boolean addRule(ControlRules rule) {
        return addRule(rule.getDevice(), rule, true);
    }

    /**
     * add and save rule to db.
     * 
     * @param device
     * @param rule
     */
    public boolean addRule(Device device, ControlRules rule) {
        return addRule(device, rule, true);
    }

    private boolean addRule(Device device, ControlRules rule, boolean saveToDb) {
        List<ControlRules> rules = mDeviceControlRules.get(device);
        if (rules == null) {
            rules = new ArrayList<ControlRules>();
            mDeviceControlRules.put(device, rules);
        }
        rules.add(rule);
        if (saveToDb) {
            return saveRule(rule);
        }
        return true;
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mDeviceManagerService = null;
            mDeviceManagerService.removeResultListener(ControlCenterService.this);
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            mDeviceManagerService = ((DeviceManagerService.MyBinder) binder).getService();
            mDeviceManagerService.addResultListeners(ControlCenterService.this);
            loadRules();
        }
    };

    @Override
    public void onNewMessage(Device device, Result result) {
        ALog.logd(ControlCenterService.this, "onreceive result:"
                + result + " device:" + device);
        Map<String, String> inputValues = new HashMap<String, String>();
        for (String status : result.getResultList()) {
            String items [] = status.split(":");
            if (items.length != 2) {
                continue;
            }
            inputValues.put(items[0], items[1]);
        }
        List<ControlRules> controlRules = mDeviceControlRules.get(device);
        if (controlRules == null || controlRules.size() <= 0) {
            return;
        }
        for (ControlRules rule : controlRules) {
            if (rule.matchRule(inputValues)) {
                rule.createDoSomethingRunnable(mDeviceManagerService).run();
            }
        }
    }

    public class MyBinder extends Binder {
        public ControlCenterService getService() {
            return ControlCenterService.this;
        }
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return new MyBinder();
    }

}
